package com.feishi.project.redirect.redirect;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.channels.SocketChannel;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: caixq
 * Date: 2020-05-29
 * Time: 下午1:49
 */
@Component
@ConfigurationProperties(prefix = "http")
@Data
public class HttpRedirect {
    private int port;
    private String targetUrl;
    private boolean end;
    @PostConstruct
    void init(){
        System.out.println(port);
        System.out.println(targetUrl);
        System.out.println(end);
        new Thread(()->{startConnect("");}).start();
        startServer();

    }
    EventLoopGroup boss = new NioEventLoopGroup();
    EventLoopGroup worker = new NioEventLoopGroup();
    public void startServer() {

        try {

            ServerBootstrap bootstrap = new ServerBootstrap();

            bootstrap.group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)// 连接数
                    .option(ChannelOption.TCP_NODELAY, true) // 不延迟，消息立即发送
                    .childOption(ChannelOption.SO_KEEPALIVE, true) // 长连接
//                    .handler()
                    .childHandler(new ChannelInitializer() {
                        @Override
                        protected void initChannel(Channel channel) throws Exception {
                            channel.pipeline().addLast(new StringDecoder());
                            // server端发送的是httpResponse，所以要使用HttpResponseEncoder进行编码
//                            channel.pipeline().addLast(
//                                    new HttpResponseEncoder());
                            // server端接收到的是httpRequest，所以要使用HttpRequestDecoder进行解码
                            channel.pipeline().addLast(
                                    new HttpRequestDecoder());

                            //增加自定义实现的Handler
//                            channel.pipeline().addLast(new HttpServerCodec());
                            channel.pipeline().addLast(new ChannelHandlerAdapter(){
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                    try {
                                        ctx.write("");
                                        String str = (String)msg;
                                        System.out.println(str);
                                    } finally {
                                        ReferenceCountUtil.release(msg);
                                    }
                                }
                            });
                        }
                    });
            ChannelFuture f = bootstrap.bind(getPort()).sync();
            if (f.isSuccess()) {
                System.out.println("启动Netty服务成功，端口号：" + getPort());
            }
            // 关闭连接
            f.channel().closeFuture().sync();

        } catch (Exception e) {
            System.err.println("启动Netty服务异常，异常信息：" + e.getMessage());
            e.printStackTrace();
        } finally {
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
    private static final Bootstrap bootstrap = new Bootstrap();
    private static final EventLoopGroup group = new NioEventLoopGroup();

    private static final int PORT = 80;

    private static final String HOST = "www.baidu.com";
    public void startConnect(String request) {
        try {
            bootstrap.group(group)
                    .remoteAddress(new InetSocketAddress(HOST, PORT))
                    //长连接
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<Channel>() {
                        protected void initChannel(Channel channel) throws Exception {

                            //包含编码器和解码器
                            channel.pipeline().addLast(new HttpClientCodec());

                            //聚合
                            channel.pipeline().addLast(new HttpObjectAggregator(1024 * 10 * 1024));

                            //解压
                            channel.pipeline().addLast(new HttpContentDecompressor());

                            channel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

                                    FullHttpResponse response = (FullHttpResponse) msg;

                                    ByteBuf content = response.content();
                                    HttpHeaders headers = response.headers();

                                    System.out.println("content:" + System.getProperty("line.separator") + content.toString(CharsetUtil.UTF_8));
                                    System.out.println("headers:" + System.getProperty("line.separator") + headers.toString());
                                }


                                @Override
                                public void channelActive(ChannelHandlerContext ctx) throws Exception {
                                    URI url = new URI("/test");
                                    String meg = "hello";

                                    //配置HttpRequest的请求数据和一些配置信息
                                    FullHttpRequest request = new DefaultFullHttpRequest(
                                            HttpVersion.HTTP_1_0, HttpMethod.GET, url.toASCIIString(), Unpooled.wrappedBuffer(meg.getBytes("UTF-8")));

                                    request.headers()
                                            .set(HttpHeaderNames.CONTENT_TYPE, "text/plain;charset=UTF-8")
                                            //开启长连接
                                            .set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE)
                                            //设置传递请求内容的长度
                                            .set(HttpHeaderNames.CONTENT_LENGTH, ""+request.content().readableBytes());

                                    //发送数据
                                    ctx.writeAndFlush(request);
                                }
                            });
                        }
                    });

            ChannelFuture channelFuture = bootstrap.connect().sync();

            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
        }

}
